/**
 * attrbute 封装
 */

import { colorValidator } from './attribute_modules/color'
import { TEL } from './attribute_modules/const'
import { LengthTest } from './attribute_modules/length'
import { UUID, uuid } from './utils'

/*----------------------------------------------------------- enum 类型的 attribute -----------------------------------------------------------*/

/**
 * 枚举类型的 attribute getter
 * @param el HTMLElement
 * @param name attribute name
 * @param enums attribute value 可选值
 */
export function enumAttrGetter<T extends HTMLElement>(el: T, name: string, enums: string[]): string | null {
  let value = el.getAttribute(name)
  if (value !== null && !enums.includes(value)) {
    value = null
  }
  return value
}

/**
 * 枚举类型的 attribute setter
 * @param el HTMLElement
 * @param name attribute name
 * @param value attribute value
 * @param enums attribute value 可选值
 */
export function enumAttrSetter<T extends HTMLElement>(el: T, name: string, value: string | null, enums: string[]): void {
  if (value && enums.includes(value)) {
    el.setAttribute(name, value)
  } else {
    el.removeAttribute(name)
  }
}

/*----------------------------------------------------------- boolean 类型的 attribute -----------------------------------------------------------*/

/**
 * 布尔类型的 attribute getter
 * @param el HTMLElement
 * @param name attribute name
 */
export function booleanAttrGetter<T extends HTMLElement>(el: T, name: string): boolean {
  const value = el.getAttribute(name)
  return value === '' || name === value ? true : false
}

/**
 * 布尔类型的 attribute setter
 * @param el HTMLElement
 * @param name attribute name
 * @param value attribute value
 */
export function booleanAttrSetter<T extends HTMLElement>(el: T, name: string, value: boolean | null): void {
  if (value === true) {
    el.setAttribute(name, '')
  } else {
    el.removeAttribute(name)
  }
}

/*----------------------------------------------------------- 颜色类型的 attribute -----------------------------------------------------------*/

/**
 * 颜色类型的 attribute getter
 */
export function colorAttrGetter<T extends HTMLElement>(el: T, name: string): string | null {
  return el.getAttribute(name)
}

/**
 * 颜色类型的 attribute setter
 * @param el HTMLElement
 * @param name attribute name
 * @param value attribute value
 */
export function colorAttrSetter<T extends HTMLElement>(el: T, name: string, value: string | null): void {
  if (typeof value === 'string') {
    const { valid, color } = colorValidator(value)
    if (valid) {
      el.setAttribute(name, color)
      return
    }
  }
  el.removeAttribute(name)
}

/*----------------------------------------------------------- length 类型的 attribute -----------------------------------------------------------*/

/**
 * length 类型的 attribute getter
 * @param el HTMLElement
 * @param name attribute name
 */
export function lengthAttrGetter<T extends HTMLElement>(el: T, name: string): string | null {
  return el.getAttribute(name)
}

/**
 * length 类型的 attribute setter
 * @param el HTMLElement
 * @param name attribute name
 * @param value attribute value
 */
export function lengthAttrSetter<T extends HTMLElement>(el: T, name: string, value: string | null): void {
  if (typeof value === 'string' && LengthTest.test(value)) {
    el.setAttribute(name, value)
  } else {
    el.removeAttribute(name)
  }
}

/*----------------------------------------------------------- string 类型的 attribute -----------------------------------------------------------*/

/**
 * string 类型的 attribute getter
 * @param el HTMLElement
 * @param name attribute name
 */
export function stringAttrGetter<T extends HTMLElement>(el: T, name: string): string | null {
  return el.getAttribute(name)
}

/**
 * string 类型的 attribute setter
 * @param el HTMLElement
 * @param name attribute name
 * @param value attribute value
 */
export function stringAttrSetter<T extends HTMLElement>(el: T, name: string, value: string | null): void {
  if (typeof value === 'string' && value.length) {
    el.setAttribute(name, value)
  } else {
    el.removeAttribute(name)
  }
}

/*----------------------------------------------------------- 的 attribute -----------------------------------------------------------*/

/**
 * 超链接值的类型
 */
export enum HREF_TYPE {
  /** 外部链接 */
  LINK = 'link',
  /** 电话 */
  TEL = 'tel',
  /** 电子邮件 */
  EMAIL = 'mailto',
  /** 下载 */
  DOWNLOAD = 'download',
  /** 锚点 */
  ANCHOR_POINT = 'anchor point',
}

export const HREF_TYPE_VALUES = Object.values(HREF_TYPE)

export const HREF_TYPE_DEFAULT = HREF_TYPE.LINK

export enum HREF_TARGET {
  TOP = '_top',
  SELF = '_self',
  BLANK = '_blank',
  PARENT = '_parent',
}

export interface HREF_DATA {
  type: HREF_TYPE
  value: string
  target?: HREF_TARGET
}

/**
 * href 类型的 attribute getter
 * @param el HTMLElement
 * @param name attribute name
 */
export function hrefAttrGetter<T extends HTMLElement>(el: T): HREF_DATA | null {
  const value = el.getAttribute('href')
  if (value) {
    const result: HREF_DATA = {
      value: value,
      type: (el.getAttribute('href-type') as HREF_TYPE) || HREF_TYPE_DEFAULT,
    }
    const target = el.getAttribute('target')
    if (target) {
      result.target = target as HREF_TARGET
    }
    return result
  }
  return null
}

/**
 * href 类型的 attribute setter
 * @param el
 * @param value
 */
export function hrefAttrSetter<T extends HTMLElement>(el: T, data: HREF_DATA | null) {
  let valid: boolean = false
  if (data) {
    switch (data.type) {
      case HREF_TYPE.LINK:
      case HREF_TYPE.DOWNLOAD:
        valid = true
        break
      case HREF_TYPE.TEL:
        valid = true
        break
      case HREF_TYPE.ANCHOR_POINT:
        valid = true
        break
    }
    if (valid) {
      el.setAttribute('href', data.value)
      el.setAttribute('href-type', data.type)
      data.target && el.setAttribute('target', data.target)
    }
  }
  if (!valid) {
    el.removeAttribute('href')
    el.removeAttribute('href-type')
    el.removeAttribute('target')
  }
}

/*---------------------------------------------------------------- id attribute ----------------------------------------------------------------*/

/**
 * 设置标签的 id 属性
 * @param el
 * @returns
 */
export function idAttrSetter<T extends HTMLElement>(el: T) {
  const root = el.getRootNode() as HTMLElement
  if (root !== el) {
    const ns = Reflect.get(el, 'idns') || 'idns'
    let id = el.id || uuid(4, ns)
    while (el !== root.querySelector(`#${id}`)) {
      id = uuid(4, ns)
    }
    el.id = id
    return id
  }
  return null
}
